---------------------------------------
--          AmBTextControl           --
---------------------------------------
-- Shows texts and streams.
local TextControl = {
   Init = function(self)
		self.TextColor = ThemeVar("default_textcontrol_text_color") or "ChatFont"
		self.TextFont = ThemeVar("default_textcontrol_font") or "ChatFont"

		self._Fragments = { } -- List of parts of text/content. can be a string or 
		-- {Function to get size(width and height), 
		--  Function to draw(x and y given)}

		self._Layout = nil -- Maps fragment indices to locations with {Line number, Offset from left, Width}
		self._LineHeight = 20 -- Height of a line.

		self._NeedHeight = 0 -- Height needed to show everything.
		self._LayoutWidth = 0 -- Width the layout is good for
   end,
	
	-- Gets the height of a single line of text.
	GetLineHeight = function(self)
		return self._LineHeight
	end,
   
   --Sets the text to show
   SetText = function(self, Value)
		self._Fragments = { }
		
		-- Set as string
		if type(Value) == "string" then
			self:_AddTextFragment(Value, nil, nil)
		end
		
		-- Set as table
		if type(Value) == "table" then
			for x = 1, #Value do
				local frag = Value[x]
				local text = frag.Text
				
				-- Formated string table
				if text != nil then
					self:_AddTextFragment(text, frag.Font, frag.Color)
				end
			end
		end
		
		self._LineHeight = 0
		self._Layout = nil
		self:_PerformLayout()
   end,
	
	_AddTextFragment = function(self, Text, Font, Color)
		for x = 1, string.len(Text) do
			local atom = string.sub(Text, x, x)
			table.insert(self._Fragments, {
				function()
					surface.SetFont(Freeze(Font or self.TextFont))
					local width, height = surface.GetTextSize(atom)
					return width, height
				end,
				function(X, Y)
					SetSurfaceTextToColor(Freeze(Color or self.TextColor))
					surface.SetFont(Freeze(Font or self.TextFont))
					surface.SetTextPos(X, Y)
					surface.DrawText(atom)
				end})
		end
	end,

   Paint = function(self)
		if self._Layout == nil then
			self:_PerformLayout()
		end
      for x = 1, #self._Fragments do
			local item = self._Fragments[x]
			local layout = self._Layout[x]
			
			-- Draw
			item[2](layout[2], layout[1] * self._LineHeight)
		end
      return false
   end,
	
	-- Performs layout on the fragments
	_PerformLayout = function(self)
		local size = self:GetWide()
		if self._Layout == nil or self._LayoutWidth != size then
			self._LayoutWidth = size
			self._Layout = { }
			local curx = 0
			local curline = 0
			for x = 1, #self._Fragments do
				local locx = 0
				local line = 0
				
				local item = self._Fragments[x]
				
				-- Get size
				local width, height = item[1]()
				self._LineHeight = math.max(self._LineHeight, height)
				
				-- X/Line
				locx = curx
				curx = locx + width
				if curx > self._LayoutWidth then
					locx = 0
					curx = width
					curline = curline + 1
				end
				line = curline
				
				self._Layout[x] = {line, locx, width}
			end
			
			self._NeedHeight = self._LineHeight * (curline + 1)
		end
	end,
	
	PanelThink = function(self)
		self:_PerformLayout()
		self:RequestResize(self:GetWide(), self._NeedHeight)
	end
}
AmB.UI.TextControl = TextControl
vgui.Register("AmBTextControl", TextControl, "AmBContentPanel")